package cn.tedu.ivos.base.aspect;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

//日志记录
@Component //需要将该类交给spring管理
@Aspect  //声明当前类是一个切面类
@Slf4j
public class AspectLog {
    //公共方法--->通知方法
    /*
      execution  --按表达式匹配
      bean  --指定对象
      within   --指定包
      @annotation  --通过注解
     */
    //execution===》匹配 多个类 多个方法
    //execution(表达式)---- 修饰符  返回值类型  包路径.类名称.方法名称(参数)
    //execution(public JonsResult cn.tedu.ivos.user.controller.UserController.login(User))  连接点
    //*表示任意的       ..表示任意参数
  //  @Pointcut("bean(userController)")
   @Pointcut("within(cn.tedu.ivos.application.controller.ApplicationController)")
     // @Pointcut("@annotation(Log)")
   // @Pointcut("execution(public * cn.tedu.ivos.*.controller.*.*(..))")
    public void anyController(){}

//    @Before("anyController()")  //前置通知，在执行方法前运行
//    //JoinPoint--存放 前端来的请求相关的信息
//    public void before(JoinPoint joinPoint){
//        requestUrl();
//        //继续输出其他参数
//        Object[] args = joinPoint.getArgs();
//        //过滤空数据，数据转成Steam
//        Stream<?> stream = ArrayUtils.isEmpty(args)? Stream.empty(): Arrays.stream(args);
//        //过滤数据 args 获取请求的信息
//        //判断当前对象属于什么类型  instanceof  不要HttpServletRequest HttpServletResponse MultipartFile
//       List<Object> collect = stream.filter(arg->(
//                !(arg instanceof HttpServletRequest)
//                && !(arg instanceof HttpServletResponse)
//                && !(arg instanceof MultipartFile)
//                )).collect(Collectors.toList());
//       //获取方法签名
//        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//        //获取类路径
//        String declaringTypeName = methodSignature.getDeclaringTypeName();
//        //获取方法名
//        String name = methodSignature.getMethod().getName();
//        //拼接要输出的内容
//       String str = declaringTypeName+"."+name+",请求参数："+ JSON.toJSONString(collect);
//       log.info("前置通知请求日志的详情：{}",str);
//    }
//
//    @After("anyController()")
//    public void after(JoinPoint joinPoint){
//        log.info("后置通知方法运行");
//    }
//    @AfterReturning("anyController()")
//    public void afterReturning(JoinPoint joinPoint){
//        log.info("最终通知方法运行"); //返回通知，运行成功后才会运行
//    }
//    @AfterThrowing("anyController()")
//    public void afterThrowing(JoinPoint joinPoint){
//        log.info("异常通知方法运行");
//    }
    //方法正常运行时：前置、后置、最终(返回)
    //方法运行异常时：前置、异常、后置
    //环绕通知：使用的不是JoinPoint，ProceedingJoinPoint，可以控制目标方法的运行
    //方法出异常时：前置、异常、后置
    //方法正常运行时：前置、返回、后置
    @Around("anyController()")
    public void around(ProceedingJoinPoint proceedingJoinPoint){
        Object result = null;
        //获取方法名称
        String methodName = proceedingJoinPoint.getSignature().getName();
        try{
            //前置通知
            log.info("这个方法的方法名为："+methodName+"开始运行，参数为："+Arrays.asList(proceedingJoinPoint.getArgs()));
            //执行目标方法
            result = proceedingJoinPoint.proceed();
            //返回（最终）通知
            log.info("这个方法最终执行完的结果为：{}",result);
        } catch (Throwable e) {
            //异常通知
            log.info("这个方法出异常了："+e);
            e.printStackTrace();
        }finally {
            //后置通知
            log.info("方法名为："+methodName+"结束运行");
        }

    }

    //打印请求的路径
    private void requestUrl(){
        //RequestContextHolder中请求信息
      ServletRequestAttributes requestAttributes =
              (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
      if(requestAttributes!=null){
          HttpServletRequest request = requestAttributes.getRequest();
          String requestURI = request.getRequestURI();
          log.info(String.format("请求URL：%s",requestURI));
      }
    }
}
